package natappvip.liujinliang.client;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import natappvip.liujinliang.common.ResponseCode;
import natappvip.liujinliang.util.FileHandler;
import natappvip.liujinliang.util.IOClosebleUtil;

/**
 * @ClassName:  ConnectionHandler   
 * @Despt: 客户端连接处理程序  
 * @Auth: Liujinliang 
 * @Date: 2018年7月29日 下午9:44:25
 */
public class ConnectionHandler {
	
	public static Logger logger = LoggerFactory.getLogger(ConnectionHandler.class);
	
	public static final String BOUNDARY = "----WebKitFormBoundary6TAB8KxvuJTZYfUn";
	
	public static final String NEWLINE = "\r\n";
	
	public static final String PREFIX = "--";
	
	/**
	 * @Title: upload   
	 * @Despt: 上传文件  
	 * @param: @param url
	 * @param: @param map
	 * @param: @param filePathes
	 * @param: @return      
	 * @return: String      
	 * @throws
	 */
	public static String upload(String url, Map<String, String> map, String[] filePathes) {
		
		// 获取 Connection
		HttpURLConnection conn = getConnection(url);
		
		// 写入参数
		setOutputStream(map, filePathes, conn);
		
		// 获取服务端返回信息
		String msg = ConnectionHandler.getInputStream(conn);
		
		return msg; 
	}
	
	/**
	 * @Title: download   
	 * @Despt: 下载文件   
	 * @param: @param url
	 * @param: @param uuid
	 * @param: @param fileName
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int download(String url, String uuid, String fileName) {
		// 获取 Connection
		HttpURLConnection conn = getConnection(url + uuid);
		
		// 保存文件
		try {
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				FileHandler.save(conn.getInputStream(), new FileOutputStream(fileName));
				return ResponseCode.SUCCESS.getCode();
			}
		} catch (FileNotFoundException e) {
			logger.info(e.getMessage());
		} catch (IOException e) {
			logger.info(e.getMessage());
		}
		
		return ResponseCode.ERROR.getCode();
	}
	
	/**
	 * @Title: mdata   
	 * @Despt: 获取文件存储的元信息   
	 * @param: @param url
	 * @param: @param uuid
	 * @param: @return      
	 * @return: String      
	 * @throws
	 */
	public static String mdata(String url, String uuid) {
		// 获取 Connection
		HttpURLConnection conn = getConnection(url + uuid);
		
		// 记录服务端返回信息
		ByteArrayOutputStream res = new ByteArrayOutputStream();
		try {
			FileHandler.save(conn.getInputStream(), res);
			return res.toString();
		} catch (IOException e) {
			logger.info(e.getMessage());
		}
		return null;
	}
	
	/**
	 * @Title: delete   
	 * @Despt: 删除文件
	 * @param: @param delLocalUrl
	 * @param: @param uuid
	 * @param: @return      
	 * @return: String      
	 * @throws
	 */
	public static String delete(String delLocalUrl, String uuid) {
		// 获取 Connection
		HttpURLConnection conn = getConnection(delLocalUrl + uuid);
		
		// 记录服务端返回信息
		ByteArrayOutputStream res = new ByteArrayOutputStream();
		
		try {
			FileHandler.save(conn.getInputStream(), res);
			return res.toString();
		} catch (IOException e) {
			logger.info(e.getMessage());
		}
		return null;
	}
	
	/**
	 * @Title: setHttpHeader   
	 * @Despt: 初始化HttpURLConnection  
	 * @param: @param conn
	 * @param: @throws ProtocolException      
	 * @return: void      
	 * @throws
	 */
	private static void setHttpHeader(HttpURLConnection conn) {
		
		conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
		
		// 设置是否向conn输出，因为是post请求，参数要放在http正文，因此需要设置为true，默认是false
		conn.setDoOutput(true); 
		
		// 设置是否向conn读入，默认是true
		conn.setDoInput(true);	
		
		// Post请求不能使用缓存
		conn.setUseCaches(false); 	
		
		//设定传送的内容是可序列化的, 参数之前由 boundary + BOUNDARY 分隔
		conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
		try {
			conn.setRequestMethod("POST");
		} catch (ProtocolException e) {
			logger.info("请求方式错误，请确认是POST或GET");
			return ;
		}	// 默认是GET
		
		// 设置字符编码链接参数
		conn.setRequestProperty("Connection", "Keep-Alive"); 
		
		// 设置字符编码
		conn.setRequestProperty("Charset", "UTF-8");	
	}
	
	/**
	 * @Title: create   
	 * @Despt: 创建 HttpURLConnection  
	 * @param: @param urlPath
	 * @param: @param conn      
	 * @return: void      
	 * @throws
	 */
	private static HttpURLConnection getConnection(String urlPath) {
		URL url = null;
		try {
			url = new URL(urlPath);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			setHttpHeader(conn);
			return conn;
		} catch (MalformedURLException e) {
			logger.info("url格式不正确");
		} catch (IOException e) {
			logger.info("HttpURLConnection 开启失败");
		}
		return null;
		
	}
	
	/**
	 * @Title: setHttpBody   
	 * @Despt: 为 HttpURLConnection 设置参数   
	 * @param: @param map
	 * @param: @param conn
	 * @param: @return      
	 * @return: String      
	 * @throws
	 */
	private static void setOutputStream(Map<String, String> map, String[] filePath, HttpURLConnection conn) {
		
		try (DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream())) {
			
			if (filePath != null && filePath.length > 0) {
				
				for (String path : filePath) {
					
					// 获取文件名称
					String fileName = path.substring(path.lastIndexOf("\\") + 1);
					
					// 参数分隔符
					dataOutputStream.writeBytes(PREFIX + BOUNDARY + NEWLINE);
					
					// 拼接参数名
					dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"file\"" + "" + ";filename=" + "\"" + fileName +"\"" + NEWLINE); 
					
					// 写文件到form表单
					FileHandler.save(new FileInputStream(fileName), dataOutputStream);
					
					// 最后换行 
					dataOutputStream.writeBytes(NEWLINE);
				}
			}
				
			if ((map != null) && (! map.isEmpty())) {
				
				for (Map.Entry<String, String> entry : map.entrySet()) {
					String key = entry.getKey();	// 键，即参数名称
					String value = map.get(key);	// 值，即参数的值
					
					// 参数分隔符
					dataOutputStream.writeBytes(PREFIX + BOUNDARY + NEWLINE);
					
					// 拼接参数名
					dataOutputStream.writeBytes("Content-Disposition: form-data; name=" + "\"" + key +"\"" + NEWLINE);
					
					// 键和值之前有空行
					dataOutputStream.writeBytes(NEWLINE);
					
					// 封装普通参数到form表单
					dataOutputStream.writeBytes(value);
					
					// 最后换行 
					dataOutputStream.writeBytes(NEWLINE);
				}
				
			}
			
			// 参数拼接完成后，需要拼接闭合字符串
			dataOutputStream.writeBytes(PREFIX + BOUNDARY + PREFIX + NEWLINE);
			
		} catch (IOException e) {
			logger.info("写入Connection的OutputStream获取失败");
		}
	}
	
	/**
	 * @Title: getInputStream   
	 * @Despt: 获取服务端传递回来的消息   
	 * @param: @param conn
	 * @param: @param byteArrayOutputStream
	 * @param: @return      
	 * @return: String      
	 * @throws
	 */
	private static String getInputStream(HttpURLConnection conn) {
		
		// 校验是否连接成功
		try {
			if (conn.getResponseCode() >= 300) {
				logger.info("Http 请求不成功，Response Code={}", conn.getResponseCode());
				return null;
			}
			// 获取服务端传递回来的消息
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
				String tmp = null;
				StringBuffer stringBuffer = new StringBuffer();
				while((tmp = reader.readLine()) != null) {
					stringBuffer.append(tmp);
					stringBuffer.append(NEWLINE);
				}
				IOClosebleUtil.closeIO(reader);
				return stringBuffer.toString();
			}
		} catch (IOException e) {
			logger.info("错误信息:{}", e.getMessage());
		}
		return null;
	}

	
}
